#include <algorithm>
#include <cfloat>
#include <cmath>
#include <fstream>
#include <iostream>
#include <iterator>
#include <ext/hash_map>
#include <map>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
#include "u1.h"

/*
 * Output a list of Netflix movie ids and their corresponding page numbers
 * in descending order by page rank. Output format is:
 * movie_id page_number
 * ...
 * where both are non-negative integers.
 *
 * Arguments (all required):
 *   -rfile : pagerank file (output from pagerank)
 *   -ifile : movie id and ordinal file (output from u1.MovieIdNumbers)
 */
using namespace std;

int main(int argc, char *argv[]) {
  string rank_file, id_file;

  /* Get arguments. */
  for (int i = 1; i < argc; ++i) {
    string arg = argv[i];
    if (arg.size() < 2) {
      TRACE << "Ignoring argument "<<arg<< ". See comments for usage."<<endl;
      continue;
    }
    string flag = arg.substr(0,2);
    if (flag == "-r") {
      rank_file = arg.substr(2);
    } else if (flag == "-i") {
      id_file = arg.substr(2);
    } else {
      TRACE << "Ignoring argument "<<arg<< ". See comments for usage."<<endl;
    }
  }
  if (rank_file.size() == 0 || id_file.size() == 0) {
    TRACE << "See comments for usage." << endl;
    exit(EXIT_FAILURE);
  }

  /* Get movie ids and page numbers (see u1/MovieIdNumbers.java). */
  map<int,int> page_movieids;
  TRACE << "Reading ids from " << id_file << "..." << endl;
  ifstream id_fs(id_file.c_str());
  while (id_fs.good()) {
    int movie_id, page_number;
    id_fs >> movie_id;
    id_fs >> page_number;
    if (id_fs.good()) {
      if (movie_id >= 0 && page_number >= 0 ) {
        page_movieids.insert(make_pair(page_number, movie_id));
      } else {
        TRACE << "Invalid page number "<<page_number<<"; ignoring."<<endl;
      }
    }
  }
  TRACE << "Read " << page_movieids.size() << " distinct movies." << endl;

  /* The pages are stored in non-increasing order by rank, so just look up the
   * appropriate movies. Output as we go. */
  TRACE << "Reading page ranks from " << rank_file << "..." << endl;
  ifstream rank_fs(rank_file.c_str());
  double last_page_rank = DBL_MAX;
  int rank_count = 0;
  while (rank_fs.good()) {
    int page_number;
    double page_rank;
    rank_fs >> page_number;
    rank_fs >> page_rank;

    // Check the rank order, just to be safe.
    if (page_rank > last_page_rank) {
      TRACE << "Rank increased at page "<<page_number<<". See usage."<<endl;
      exit(EXIT_FAILURE);
    }
    last_page_rank = page_rank;

    if (rank_fs.good()) {
      map<int,int>::const_iterator it = page_movieids.find(page_number);
      if (it != page_movieids.end()) {
        cout << it->second << " " << page_number << endl;
        ++rank_count;
      }
    }
  }
  TRACE << "Ranked " << rank_count << " movies." << endl;

  return 0;
}

/*
* Copyright (c) 2009 John Lees-Miller
* 
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
* 
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

